//-------------------------------------------------------------------------------------------------
// Copyright (c) Bradford W. Mott and Flare Contributors
// North Carolina State University, Department of Computer Science
// The IntelliMedia Group
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
// OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//-------------------------------------------------------------------------------------------------

using Flare.Display;

namespace Flare.Events
{
    /// <summary>
    /// The MouseEvent class provides an event that is dispatched into the eventflow
    /// when mouse events occur.
    /// </summary>
    public class MouseEvent : Event
    {
        /// <summary>
        /// Indicates if Alt key is pressed (Option key on Mac, 
        /// Alt key on Windows or Linux).
        /// </summary>
        public bool altKey { get; set; }

        /// <summary>
        /// Indicates if the primary mouse button is pressed.
        /// </summary>
        public bool buttonDown { get; set; }

        /// <summary>
        /// Indicates if the Ctrl key is pressed (Control or Command key on Mac,
        /// Ctrl key on Windows or Linux).
        /// </summary>
        public bool ctrlKey { get; set; }

        /// <summary>
        /// Indicates if the shift key is pressed.
        /// </summary>
        public bool shiftKey { get; set; }

        // TODO bwmott 2013-03-17: In AS3 localX and localY setters are public; however, they
        // also cause corresponding updates to stageX and stageY. The stageX and stageY values
        // can be calculated using transformPoint(localX, localY) on the inverse of the
        // traget.trans.concatenatedMatrix matrix. For now, we are making these setters private.

        /// <summary>
        /// Gets the local x coordinate (relative to the containing display object) of the event.
        /// </summary>
        public float localX { get;
            /* \cond */ private set; /* \endcond */ }

        /// <summary>
        /// Gets the local y coordinate (relative to the containing display object) of the event.
        /// </summary>
        public float localY { get;
            /* \cond */ private set; /* \endcond */ }

        /// <summary>
        /// The display object related to the event.
        /// </summary>
        public InteractiveObject relatedObject { get; set; }

        /// <summary>
        /// Gets the x coordinate of the event in global stage coordinates.
        /// </summary>
        public float stageX { get; 
            /* \cond */ private set; /* \endcond */ }

        /// <summary>
        /// Gets the y coordinate of the event in global stage coordinates.
        /// </summary>
        public float stageY { get; 
            /* \cond */ private set; /* \endcond */ }

        /// <summary>
        /// Create a new instance of the MouseEvent class.
        /// </summary>
        public MouseEvent(string type, bool bubbles = true, bool cancelable = false,
            float localX = global::System.Single.NaN, float localY = global::System.Single.NaN,
            float stageX = global::System.Single.NaN, float stageY = global::System.Single.NaN,
            InteractiveObject relatedObject = null,
            bool ctrlKey = false, bool altKey = false, bool shiftKey = false,
            bool buttonDown = false)
            : base(type, bubbles, cancelable)
        {
            this.altKey = altKey;
            this.buttonDown = buttonDown;
            this.ctrlKey = ctrlKey;
            this.shiftKey = shiftKey;
            this.relatedObject = relatedObject;
            this.localX = localX;
            this.localY = localY;
            this.stageX = stageX;
            this.stageY = stageY;
        }

        public override string ToString()
        {
            return string.Format("[MouseEvent type=\"{0}\" bubbles={1} cancelable={2} " +
                "eventPhase={3} localX={4} localY={5} stageX={6} stageY={7} relatedObject={8} " +
                "ctrlKey={9} altKey={10} shiftKey={11} buttonDown={12}]",
                this.type, this.bubbles, this.cancelable,
                this.eventPhase, this.localX, this.localY, this.stageX, this.stageY,
                this.relatedObject, this.ctrlKey, this.altKey, this.shiftKey, this.buttonDown);
        }

        /// <summary>
        /// mouseDown event is dispatched when the primary mouse button is pressed on the stage.
        /// </summary>
        public const string MOUSE_DOWN = "mouseDown";

        /// <summary>
        /// mouseMove event is dispatched when the mouse pointer moves on the stage.
        /// </summary>
        public const string MOUSE_MOVE = "mouseMove";

        /// <summary>
        /// mouseUp event is dispatched when the primary mouse button is released on the stage.
        /// </summary>
        public const string MOUSE_UP = "mouseUp";

        /// <summary>
        /// rightMouseDown event is dispatched when the primary mouse button is pressed on the stage.
        /// </summary>
        public const string RIGHT_MOUSE_DOWN = "rightMouseDown";

        /// <summary>
        /// rightMouseUp event is dispatched when the primary mouse button is released on the stage.
        /// </summary>
        public const string RIGHT_MOUSE_UP = "rightMouseUp";
    }
}
